import os
import uuid
from datetime import datetime
from sqlalchemy.orm import Session
from sqlalchemy import and_, or_, desc
from typing import Dict, Any, List, Optional
import math

from models import FileUpload, Report, Merchant
import schemas

# 文件系统存储的根目录
UPLOAD_DIR = os.getenv("UPLOAD_DIR", "uploads")

def save_to_filesystem(file_content: bytes, filename: str, merchant_id: int, report_id: int) -> str:
    """
    将文件保存到文件系统
    
    Args:
        file_content: 文件内容
        filename: 文件名
        merchant_id: 商户ID
        report_id: 报告ID
        
    Returns:
        保存的文件路径
    """
    # 确保上传目录存在
    today = datetime.now().strftime("%Y/%m/%d")
    upload_path = os.path.join(UPLOAD_DIR, str(merchant_id), str(report_id), today)
    os.makedirs(upload_path, exist_ok=True)
    
    # 使用UUID生成唯一文件名
    file_uuid = str(uuid.uuid4())
    file_ext = os.path.splitext(filename)[1] if '.' in filename else ''
    unique_filename = f"{file_uuid}{file_ext}"
    file_path = os.path.join(upload_path, unique_filename)
    
    # 获取绝对路径，确保与read_from_filesystem一致
    abs_path = os.path.abspath(file_path)
    
    # 写入文件
    with open(abs_path, "wb") as f:
        f.write(file_content)
    
    return file_path  # 返回相对路径，保持数据库记录的一致性

def read_from_filesystem(file_path: str) -> bytes:
    """
    从文件系统读取文件内容
    
    Args:
        file_path: 文件路径
        
    Returns:
        文件内容
    """
    # 确保是绝对路径
    if not os.path.isabs(file_path):
        # 如果是相对路径，则相对于当前工作目录
        file_path = os.path.abspath(file_path)
    
    # 检查文件是否存在
    if not os.path.exists(file_path):
        raise FileNotFoundError(f"文件不存在: {file_path}")
        
    with open(file_path, "rb") as f:
        return f.read()

def get_content_type(file_format: str) -> str:
    """
    根据文件格式获取内容类型
    在我上传时。
    Args:
        file_format: 文件格式
        
    Returns:
        内容类型
    """
    content_types = {
        "pdf": "application/pdf",
        "xlsx": "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet",
        "xls": "application/vnd.ms-excel",
        "docx": "application/vnd.openxmlformats-officedocument.wordprocessingml.document",
        "doc": "application/msword",
        "pptx": "application/vnd.openxmlformats-officedocument.presentationml.presentation",
        "ppt": "application/vnd.ms-powerpoint",
        "jpg": "image/jpeg",
        "jpeg": "image/jpeg",
        "png": "image/png",
        "txt": "text/plain",
        "csv": "text/csv",
    }
    
    return content_types.get(file_format.lower(), "application/octet-stream")

def get_merchant_files(db: Session, merchant_id: int) -> List[FileUpload]:
    """
    获取指定商户的所有有效文件
    
    Args:
        db: 数据库会话
        merchant_id: 商户ID
        
    Returns:
        该商户的所有有效文件列表
    """
    return db.query(FileUpload).filter(
        FileUpload.merchant_id == merchant_id,
        FileUpload.status == 1
    ).order_by(FileUpload.file_type).all()

def upload_file(db: Session, file_info: Dict[str, Any]) -> FileUpload:
    """
    上传文件
    
    Args:
        db: 数据库会话
        file_info: 文件信息
        
    Returns:
        上传的文件记录
    """
    # 1. 将同一商户同类型的旧文件标记为无效
    old_files = db.query(FileUpload).filter(
        FileUpload.merchant_id == file_info["merchant_id"],
        FileUpload.file_type == file_info["file_type"],
        FileUpload.status == 1
    ).all()
    
    for old_file in old_files:
        old_file.status = 0
        old_file.remark = (old_file.remark or "") + f" 被新上传文件替换于{datetime.now()}"
    
    # 2. 创建新文件记录
    file_upload = FileUpload(
        report_id=file_info["report_id"],
        merchant_id=file_info["merchant_id"],
        file_name=file_info["file_name"],
        file_path=file_info.get("file_path"),
        file_size=file_info["file_size"],
        file_type=file_info["file_type"],
        file_format=file_info["file_format"],
        file_content=file_info.get("file_content"),
        store_type=file_info["store_type"],
        upload_time=datetime.now(),
        status=1,
        process_status=0,
        operator=file_info.get("operator"),
        remark=file_info.get("remark")
    )
    
    db.add(file_upload)
    
    # 3. 更新报告状态
    update_report_status(db, file_info["report_id"])
    
    db.commit()
    db.refresh(file_upload)
    
    return file_upload

def update_report_status(db: Session, report_id: int) -> None:
    """
    更新报告状态
    
    Args:
        db: 数据库会话
        report_id: 报告ID
    """
    # 1. 获取报告信息
    report = db.query(Report).filter(Report.id == report_id).first()
    if not report:
        return
    
    # 2. 统计有效文件数量
    file_count = db.query(FileUpload).filter(
        FileUpload.report_id == report_id,
        FileUpload.status == 1
    ).count()
    
    # 3. 更新报告状态
    report.file_count = file_count
    if file_count == 0:
        report.status = 0  # 未完成
    elif file_count < report.expected_file_count:
        report.status = 1  # 部分完成
    else:
        report.status = 2  # 已完成
    
    db.commit()

def get_file_list(db: Session, filters: Dict[str, Any], page_num: int, page_size: int) -> Dict[str, Any]:
    """
    获取文件列表
    
    Args:
        db: 数据库会话
        filters: 过滤条件
        page_num: 页码
        page_size: 每页记录数
        
    Returns:
        文件列表
    """
    # 构建查询条件
    query = db.query(FileUpload, Merchant.name.label("merchant_name")).join(
        Merchant, FileUpload.merchant_id == Merchant.id
    )
    
    # 应用过滤条件
    for key, value in filters.items():
        if hasattr(FileUpload, key):
            query = query.filter(getattr(FileUpload, key) == value)
    
    # 获取总记录数
    total = query.count()
    
    # 分页
    query = query.order_by(desc(FileUpload.upload_time))
    query = query.offset((page_num - 1) * page_size).limit(page_size)
    
    # 执行查询
    results = query.all()
    
    # 构建返回数据
    files = []
    for file_upload, merchant_name in results:
        files.append({
            "fileId": file_upload.id,
            "reportId": file_upload.report_id,
            "merchantId": file_upload.merchant_id,
            "merchantName": merchant_name,
            "fileName": file_upload.file_name,
            "fileType": file_upload.file_type,
            "fileSize": file_upload.file_size,
            "storeType": file_upload.store_type,
            "status": file_upload.status,
            "processStatus": file_upload.process_status,
            "uploadTime": file_upload.upload_time.strftime("%Y-%m-%d %H:%M:%S"),
            "operator": file_upload.operator
        })
    
    return {
        "total": total,
        "pageNum": page_num,
        "pageSize": page_size,
        "list": files
    }

def get_file_by_id(db: Session, file_id: int) -> Optional[FileUpload]:
    """
    根据ID获取文件
    
    Args:
        db: 数据库会话
        file_id: 文件ID
        
    Returns:
        文件记录
    """
    return db.query(FileUpload).filter(FileUpload.id == file_id).first()

def delete_file(db: Session, file_id: int) -> bool:
    """
    删除文件
    
    Args:
        db: 数据库会话
        file_id: 文件ID
        
    Returns:
        是否成功
    """
    file = db.query(FileUpload).filter(FileUpload.id == file_id).first()
    if not file:
        return False
    
    # 标记为无效
    file.status = 0
    
    # 更新报告状态
    update_report_status(db, file.report_id)
    
    db.commit()
    
    return True 